package hn.cch.spring_async_call.task;

import hn.cch.spring_async_call.service.ApiService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 默认情况：Initializing ExecutorService 'taskScheduler'
 */
@EnableScheduling
@Configuration
public class ApiTask {

    private Logger logger = LoggerFactory.getLogger(ApiTask.class);

    @Autowired
    private ApiService apiService;


    /**
     * spring boot 低版本
     * implements SchedulingConfigurer
     * @Override configureTasks
     * @param scheduledTaskRegistrar
     */
    // @Override
    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
        ScheduledThreadPoolExecutor threadPoolExecutor =  new ScheduledThreadPoolExecutor(
                4,// 核心线程数
                runnable -> new Thread(runnable, "pool-" + runnable.hashCode()),// 线程工厂
                new ThreadPoolExecutor.AbortPolicy()// 拒绝策略
        );

        scheduledTaskRegistrar.setScheduler(threadPoolExecutor);

    }

    @Scheduled(cron = "44 28 14 ? * 1")
    public void testCron(){
        logger.info("test cron");
    }


    /**
     * 加上@Async会使用自定义异步线程池taskExecutor
     */
    // @Async
    // @Scheduled(cron = "${cron.task.api.test}")
    public void testTask() {
        logger.info("testTask start");
        try {
            Thread.sleep(10 * 1000);
        } catch (InterruptedException e) {
            logger.error(e.getMessage());
        }
        logger.info("testTask stop");
    }

    // 两个异步任务
    @Async
    // @Scheduled(cron = "*/5 * * * * ?")
    public void testAsyncTask0() {
        logger.info("testAsyncTask0");
        try {
            Thread.sleep(10 * 1000);
        } catch (InterruptedException e) {
            logger.error(e.getMessage());
        }
    }

    @Async
    // @Scheduled(cron = "*/5 * * * * ?")
    public void testAsyncTask1() {
        logger.info("testAsyncTask1");
        try {
            Thread.sleep(10 * 1000);
        } catch (InterruptedException e) {
            logger.error(e.getMessage());
        }
    }

    // 两个同步任务
    // @Scheduled(cron = "*/5 * * * * ?")
    public void testTask0() {
        logger.info("testTask0");
        try {
            Thread.sleep(10 * 1000);
        } catch (InterruptedException e) {
            logger.error(e.getMessage());
        }
    }

    // @Scheduled(cron = "*/5 * * * * ?")
    public void testTask1() {
        logger.info("testTask1");
        try {
            Thread.sleep(10 * 1000);
        } catch (InterruptedException e) {
            logger.error(e.getMessage());
        }
    }


    // @Scheduled(cron = "${cron.task.api.test}")
    public void demoTask() {
        logger.info("demoTask start");
        ThreadPoolExecutor threadPoolExecutor = threadPoolExecutor();
        int num = 10;
        final CountDownLatch countDownLatch = new CountDownLatch(num);
        List<Future> futureList = new ArrayList<>();
        for (int i = 0; i < num; i++) {
            Future<String> future = threadPoolExecutor.submit(() -> {
                try {
                    Thread.sleep(1 * 1000);
                } catch (InterruptedException e) {
                    logger.error(e.getMessage());
                }
                logger.info("task call done");
                countDownLatch.countDown();
                return "call:" + UUID.randomUUID();
            });
            futureList.add(future);
        }

        try {
            //等待线程池的等待队列中的任务执行完成
            countDownLatch.await();
            for (Future future : futureList) {
                logger.info("task:{}", future.get());
            }
        } catch (Exception e) {
            logger.error(e.getMessage());
        }
        logger.info("demoTask stop");
    }


    /**
     * 建议不要使用Executors创建线程池
     *
     * @return
     */
    public ThreadPoolExecutor threadPoolExecutor() {


        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                4,// 核心线程数
                8,// 最大线程数
                60,// 空闲线程（超过核心线程数的线程）存活时间
                TimeUnit.SECONDS,// 存活时间对应单位
                new ArrayBlockingQueue<Runnable>(100),// 任务队列
                runnable -> new Thread(runnable, "pool-" + runnable.hashCode()),// 线程工厂
                new ThreadPoolExecutor.AbortPolicy()// 拒绝策略

        );
        return threadPoolExecutor;
    }


}
